/* eslint-disable no-cond-assign */
/* eslint-disable no-unused-vars */
/* eslint-disable no-undef */
function highlightGroup (e, grp, show, o) {
  if (!grp) return
  e.handled = true
  if (show) {
    // cannot depend on the grp.diagram.selection in the case of external drag-and-drops;
    // instead depend on the DraggingTool.draggedParts or .copiedParts
    var tool = grp.diagram.toolManager.draggingTool
    var map = tool.draggedParts || tool.copiedParts  // o is a Map
    // now we can check to see if the Group will accept membership of the dragged Parts
    if (grp.canAddMembers(map.toKeySet())) {
      grp.isHighlighted = true
      return
    }
  }
  grp.isHighlighted = false
}
function finishDrop (e, grp, name, o) {
  // console.log(e, grp)
  var ok = (grp !== null
    ? grp.addMembers(grp.diagram.selection, true)
    : e.diagram.commandHandler.addTopLevelParts(e.diagram.selection, true))
  if (!ok) { e.diagram.currentTool.doCancel() }
}
export function init (o, serviceArr, nodeArr, linkArr, showObj = {}) {
  let serviceArr1 = []
  serviceArr.forEach((item, k) => {
    item.text = item.cmpId
    item.key = item.cmpId
    item.type = 'service'
    item.source = require('../../assets/img/element/service.jpg')
    serviceArr1.push(item)
  })
  if (o.myDiagram) {
    o.myDiagram.div = null
    o.myPalette.div = null
    o.myPaletteSafe.div = null
    o.myPaletteService.div = null
  }
  let $ = go.GraphObject.make
  o.myDiagram =
    $(go.Diagram, 'myDiagramDiv',
      {
        // what to do when a drag-drop occurs in the Diagram's background
        mouseDrop: (e) => { finishDrop(e, null, 'body', o) },
        'commandHandler.archetypeGroupData': { isGroup: true, category: 'OfNodes' },
        'undoManager.isEnabled': true,
        initialAutoScale: go.Diagram.Uniform,
        contentAlignment: go.Spot.Center,
        layout: $(go.ForceDirectedLayout,
          { maxIterations: 200, defaultSpringLength: 30, defaultElectricalCharge: 100 })
      })
  // Upon a drop onto a Group, we try to add the selection as members of the Group.
  // Upon a drop onto the background, or onto a top-level Node, make selection top-level.
  // If o is OK, we're done; otherwise we cancel the operation to rollback everything.
  // let that = o
  o.myDiagram.groupTemplateMap.add('OfGroups',
    $(go.Group, 'Vertical',
      {
        background: 'transparent',
        // highlight when dragging into the Group
        mouseDragEnter: (e, grp, prev) => { highlightGroup(e, grp, true, o) },
        mouseDragLeave: (e, grp, next) => { highlightGroup(e, grp, false, o) },
        computesBoundsAfterDrag: true,
        // when the selection is dropped into a Group, add the selected Parts into that Group;
        // if it fails, cancel the tool, rolling back any changes
        mouseDrop: (e, nod) => { finishDrop(e, nod, 'parent', o) },
        mouseLeave: (e, node) => {
          // console.log('fff')
          if (e.diagram.div.id !== 'myDiagramDiv') {
            let time = `D${(new Date()).getTime()}`
            node.data.text = time
            node.data.key = time
            node.data.domainId = time
            node.data.domainName = time
          }
        },
        handlesDragDropForMembers: true,  // don't need to define handlers on member Nodes and Links
        // Groups containing Groups lay out their members horizontally
        layout: $(go.GridLayout, { wrappingWidth: 250, alignment: go.Spot.TopLeft })
      },
      new go.Binding('background', 'isHighlighted', function (h) { return h ? 'rgba(255,0,0,0.2)' : 'transparent' }).ofObject(),
      {
        fromSpot: go.Spot.Center,
        toSpot: go.Spot.Center,
        fromLinkable: true,
        toLinkable: true,
        locationSpot: go.Spot.Center
      },
      $(go.Panel, 'Auto',  // title above Placeholder
      $(go.Shape, 'Rectangle',
        { fill: null, minSize: new go.Size(100, 100), stroke: 'gray' }),
        $(go.Placeholder, { padding: 15 })
      ),  // end Vertical Panel
      $(go.TextBlock,
        {
          alignment: go.Spot.Center,
          editable: true,
          margin: 5,
          font: 'bold 18px sans-serif',
          opacity: 0.75,
          fromLinkable: false,
          toLinkable: false
        },
        new go.Binding('text', 'text').makeTwoWay())
    ))  // end Group and call to add to template Map
  o.myDiagram.nodeTemplate =
    $(go.Node, 'Vertical',
      {
        fromSpot: go.Spot.Center,
        toSpot: go.Spot.Center,
        fromLinkable: true,
        toLinkable: true,
        locationSpot: go.Spot.Center
      },
      $(go.Picture,
        // eslint-disable-next-line standard/object-curly-even-spacing
        { width: 60, height: 60},
        new go.Binding('source')),
      $(go.TextBlock,
        {
          opacity: 0.75,
          font: 'bold 16px sans-serif',
          fromLinkable: false,
          toLinkable: false
        },
        new go.Binding('text', 'text').makeTwoWay()),
      {
        // dropping on a Node is the same as dropping on its containing Group, even if it's top-level
        doubleClick: (e, node) => {
          if (showObj.isEdit) {
            o.targetNode = node.part.data
            if (o.targetNode.type === 'firewall') {
              o.targetFire = Object.assign({}, o.targetNode)
              o.$refs.fireWall.showDialog(o.targetNode.key)
            } else if (o.targetNode.type === 'vpn') {
              o.targetVpn = Object.assign({}, o.targetNode)
              o.$refs.vpn.showVpn(o.targetNode.key)
            }
          }
        },
        mouseLeave: (e, node) => {
          if (e.diagram.div.id !== 'myDiagramDiv') {
            let time = (new Date()).getTime()
            if (node.data.type === 'vpn') {
              node.data.key = node.data.text = `V${time}`
            } else if (node.data.type === 'firewall') {
              node.data.key = node.data.text = `W${time}`
            } else {
              node.data.key = node.data.text = node.data.cmpId
            }
          }
        },
        selectionChanged: (node) => {
          o.selectNode = node.data
        }
      }
    )
  // initialize the Palette and its contents
  o.myPaletteSafe =
    $(go.Palette, 'myPaletteSafeDiv',
      {
        nodeTemplateMap: o.myDiagram.nodeTemplateMap,
        groupTemplateMap: o.myDiagram.groupTemplateMap,
        layout: $(go.GridLayout),
        model: new go.GraphLinksModel([
          { type: 'safe', text: '安全域', key: '', 'isGroup': true, 'category': 'OfGroups', accessNetwork: null, cipherMachine: null, domainId: null, domainName: '', domainType: '0', elementCount: 1, state: null, stateMessage: null }
        ])
      })
  o.myPalette =
    $(go.Palette, 'myPaletteServiceDiv',
      {
        nodeTemplateMap: o.myDiagram.nodeTemplateMap,
        groupTemplateMap: o.myDiagram.groupTemplateMap,
        layout: $(go.GridLayout),
        model: new go.GraphLinksModel([
          // eslint-disable-next-line standard/object-curly-even-spacing
          {type: 'vpn', text: 'vpn', key: '', inPortId: 1, outPortId: 2, state: null, stateMessage: null, vnfIndex: null, vpn: null, createVM: null, firewall: null, source: require('../../assets/img/element/vpn.jpg') },
          {type: 'firewall', text: '防火墙', key: '', inPortId: 1, outPortId: 2, state: null, stateMessage: null, vnfIndex: null, vpn: null, createVM: null, firewall: null, source: require('../../assets/img/element/firewall.jpg')}
        ])
      })
  o.myPaletteService =
    $(go.Palette, 'myPaletteDiv',
      {
        nodeTemplateMap: o.myDiagram.nodeTemplateMap,
        groupTemplateMap: o.myDiagram.groupTemplateMap,
        layout: $(go.GridLayout),
        model: new go.GraphLinksModel(serviceArr1)
      })
  if (nodeArr.length) {
    o.myDiagram.model = new go.GraphLinksModel(nodeArr, linkArr)
  }
  o.myDiagram.commandHandler.memberValidation = function (grp, node) {
    if (node.data.type !== 'service') {
      return false
    }
    if (grp instanceof go.Group && node instanceof go.Group) {
      return false  // cannot add Groups to Groups
    }
    return true
  }
  o.myDiagram.addDiagramListener('LinkDrawn', (e) => {
    if (e.subject.data.to.indexOf('.') !== -1 || e.subject.data.from.indexOf('.') !== -1) {
      o.myDiagram.model.removeLinkData(e.subject.data)
    }
  })
  // 节点生成事件
  o.myDiagram.addDiagramListener('externalobjectsdropped', (e) => {
    e.subject.each((n) => {
      if (n.data.type === 'service') {
        o.myPaletteService.commandHandler.deleteSelection()
      }
    })
  })
  // 删除后事件
  o.myDiagram.addDiagramListener('SelectionDeleted', (e) => {
    e.subject.each((n) => {
      if (n.data.type === 'service') {
        o.myPaletteService.model.addNodeData(n.data)
      }
    })
  })
  // 监听当前拖过来的节点是否是资源组件
  o.myDiagram.addDiagramListener('ExternalObjectsDropped', function (e) {
    e.subject.each(function (n) {
      if (n.data.type === 'service') {
        if (n.containingGroup == null) {
          e.diagram.commandHandler.deleteSelection()
          o.$message({
            message: '虚拟机只能放在安全域中',
            type: 'warning'
          })
        }
      }
    })
  })
}
